package com.ruoyi.user.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.core.pojo.request.PageParam;
import com.ruoyi.common.core.pojo.result.PageUtils;
import com.ruoyi.common.core.pojo.result.Pages;
import com.ruoyi.common.core.utils.CollectionUtils;
import com.ruoyi.common.core.utils.CommonUtils;

import com.ruoyi.common.core.utils.DateUtils;
import com.ruoyi.user.mapper.AttentionMapper;
import com.ruoyi.user.model.constant.UserConstant;
import com.ruoyi.user.model.pojo.entity.Attention;
import com.ruoyi.user.model.pojo.entity.Balance;
import com.ruoyi.user.model.pojo.entity.User;
import com.ruoyi.user.model.pojo.entity.UserBlack;
import com.ruoyi.user.model.pojo.request.app.AppUserSetIsLookRequest;
import com.ruoyi.user.model.pojo.request.app.AppUserSetNoteNameRequest;
import com.ruoyi.user.model.pojo.result.NotReadInfo;
import com.ruoyi.user.model.pojo.result.UserFansInfo;
import com.ruoyi.user.service.IAttentionService;
import com.ruoyi.user.service.IUserBlackService;
import com.ruoyi.user.service.IUserService;
import io.lettuce.core.RedisClient;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * <p>
 * 关注表 服务实现类
 * </p>
 *
 * @author ${author}
 * @since 2023-05-21
 */
@Service
public class AttentionServiceImpl extends ServiceImpl<AttentionMapper, Attention> implements IAttentionService {
    @Autowired

    private IUserService iUserService;
    @Autowired
    private IUserBlackService userBlackService;
    @Autowired
    private RedissonClient redissonClient;

    @Override
    public Integer attention(Long userId, Long aimUserId) {
        Assert.isTrue(!userId.equals(aimUserId), "自己不能关注自己");
        Long count = lambdaQuery().eq(Attention::getUserId, userId)
                .eq(Attention::getAimUserId, aimUserId)
                .count();
        if (count > 0) {
            lambdaUpdate().eq(Attention::getUserId, userId)
                    .eq(Attention::getAimUserId, aimUserId)
                    .remove();
        } else {
            Attention attention = new Attention();
            attention.setUserId(userId);
            attention.setAimUserId(aimUserId);
            save(attention);
        }
        return isAttention(userId, aimUserId);
    }

    @Override
    public Integer attention(Long userId, Long aimUserId, Integer intimacyNum) {
        RLock lock = redissonClient.getLock("attention" + userId + aimUserId);
        try {
            if (lock.tryLock(10, 5, TimeUnit.SECONDS)) {
                //增加双方好友及亲密度
                Attention one = lambdaQuery()
                        .eq(Attention::getUserId, userId)
                        .eq(Attention::getAimUserId, aimUserId).one();
                if (CommonUtils.isNull(one)) {
                    one = new Attention();
                    one.setAimUserId(aimUserId);
                    one.setUserId(userId);
                    one.setIntimacyNum(intimacyNum);
                } else {
                    one.setIntimacyNum(one.getIntimacyNum() + intimacyNum);
                }
                saveOrUpdate(one);
                return 0;
            }
        } catch (InterruptedException e) {
            // 抛出异常 操作失败
            return 1;
        } finally {
            if (lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
        return 0;
    }

    @Override
    public Integer isAttention(Long userId, Long aimUserId) {
        // 如果是自己看自己视频则返回互关
        if (userId.equals(aimUserId)) return UserConstant.Attention.oneselfAttention;
        Long attentionCount = lambdaQuery().eq(Attention::getUserId, userId)
                .eq(Attention::getAimUserId, aimUserId)
                .count();
        Long aimAttentionCount = lambdaQuery().eq(Attention::getUserId, aimUserId)
                .eq(Attention::getAimUserId, userId)
                .count();
        if (attentionCount == 0 && aimAttentionCount == 0) {
            return UserConstant.Attention.attention;
        } else if (attentionCount > 0 && aimAttentionCount == 0) {
            return UserConstant.Attention.alreadyAttention;
        } else if (attentionCount == 0) {
            return UserConstant.Attention.answerAttention;
        } else {
            return UserConstant.Attention.mutualAttention;
        }
    }

    @Override
    public Long beAttentionCount(Long userId) {
        return lambdaQuery().eq(Attention::getAimUserId, userId)
                .count();
    }

    @Override
    public Set<Long> attentionUserIds(Long userId) {
        return lambdaQuery().eq(Attention::getUserId, userId)
                .select(Attention::getAimUserId)
                .list()
                .stream()
                .map(Attention::getAimUserId)
                .collect(Collectors.toSet());
    }

    @Override
    public Long attentionUserCount(Long userId) {
        return lambdaQuery().eq(Attention::getUserId, userId)
                .count();
    }

    @Override
    public Long notReadAttention(Long userId) {
        return notReadAttention(userId, null);
    }

    @Override
    public Long notReadAttention(Long userId, Integer isRead) {
        return lambdaQuery().eq(Attention::getAimUserId, userId)
                .ne(Attention::getUserId, userId)
                .eq(!CommonUtils.isNull(isRead), Attention::getIsRead, isRead)
                .count();
    }

    @Override
    public Attention lastAttention(Long userId) {
        Page<Attention> page = PageUtils.initPage(1, 1);
        Page<Attention> attentionPage = lambdaQuery().eq(Attention::getAimUserId, userId)
                .ne(Attention::getUserId, userId)
                .orderByDesc(Attention::getCreateTime)
                .page(page);
        if (attentionPage.getRecords().isEmpty()) return new Attention();
        return attentionPage.getRecords().get(0);
    }


    @Override
    public Pages<UserFansInfo> fansList(PageParam pageSearchParam, Long userId) {
        Page<Attention> userPage = PageUtils.initPage(pageSearchParam, Attention.class);
        Page<Attention> page = lambdaQuery().eq(Attention::getAimUserId, userId)
                .ne(Attention::getUserId, userId)
                .orderByDesc(Attention::getCreateTime)
                .page(userPage);
        if (page.getRecords().isEmpty()) return PageUtils.pages(userPage, CollectionUtils.emptyList());
        List<UserFansInfo> userSearchInfos = new ArrayList<>();
        for (Attention attention : page.getRecords()) {
            Attention one = lambdaQuery().eq(Attention::getAimUserId, attention.getUserId()).eq(Attention::getUserId, userId).one();
            User userInfo = iUserService.findUserInfo(attention.getUserId());
            if (!CommonUtils.isNull(userInfo)) {
                UserFansInfo build = UserFansInfo.builder()
                        .id(attention.getId())
                        .userId(userInfo.getId())
                        .phone(userInfo.getPhone())
                        .photo(userInfo.getPhoto())
                        .nickname(userInfo.getNickName())
                        .isAttention(isAttention(userId, attention.getUserId()))
                        .createTime(attention.getCreateTime())
                        .isBlock(attention.getIsBlock())
                        .isLook(attention.getIsLook())
                        .noteName(!CommonUtils.isNull(one) ? one.getNoteName() : "")
                        .build();
                userSearchInfos.add(build);
            }
        }
        return PageUtils.pages(page, userSearchInfos);
    }

    @Override
    public NotReadInfo notMessage(Long userId) {
        Attention attention = lastAttention(userId);
        Long notReadAttention = notReadAttention(userId, UserConstant.Read.not);
        String newAttentionCount = "暂无消息";
        if (!CommonUtils.isNull(attention.getUserId())) {
            User userInfo = iUserService.findUserInfo(attention.getUserId());
            if (!CommonUtils.isNull(userInfo)) {
                newAttentionCount = userInfo.getNickName() + "等" + notReadAttention(userId) + "位用户关注了你";
            }
        }
        return NotReadInfo.builder()
                .newAttentionCount(notReadAttention)
                .newAttentionContent(newAttentionCount)
                .newAttentionCreateTime(Optional.ofNullable(attention.getCreateTime()).orElse(DateUtils.currentDate()))
                .build();
    }

    @Override
    public Pages<UserFansInfo> attentionList(PageParam pageSearchParam, Long userId) {
        Page<Attention> userPage = PageUtils.initPage(pageSearchParam, Attention.class);
        //不查询拉黑我的用户和我拉黑的用户
        Set<Long> userblackIds = userBlackService.lambdaQuery().eq(UserBlack::getUserId, userId).list().stream().map(UserBlack::getAimUserId).collect(Collectors.toSet());

        Page<Attention> page = lambdaQuery().eq(Attention::getAimUserId, userId)
                .eq(Attention::getUserId, userId)
                .ne(!userblackIds.isEmpty(), Attention::getAimUserId, userblackIds)
                .orderByDesc(Attention::getCreateTime)
                .page(userPage);
        if (page.getRecords().isEmpty()) return PageUtils.pages(userPage, CollectionUtils.emptyList());
        List<UserFansInfo> userSearchInfos = new ArrayList<>();
        for (Attention attention : page.getRecords()) {
            User userInfo = iUserService.findUserInfo(attention.getAimUserId());
            UserFansInfo build = UserFansInfo.builder()
                    .id(attention.getId())
                    .userId(userInfo.getId())
                    .phone(userInfo.getPhone())
                    .photo(userInfo.getPhoto())
                    .nickname(userInfo.getNickName())
                    .isAttention(isAttention(userId, attention.getAimUserId()))
                    .createTime(attention.getCreateTime())
                    .noteName(attention.getNoteName())
                    .isBlock(attention.getIsBlock())
                    .isLook(attention.getIsLook())
                    .build();
            userSearchInfos.add(build);
        }
        return com.ruoyi.common.core.pojo.result.PageUtils.pages(page, userSearchInfos);
    }

    @Override
    public Pages<UserFansInfo> mutualList(PageParam pageSearchParam, Long userId) {
        Page<Attention> userPage = PageUtils.initPage(pageSearchParam, Attention.class);
        //先获取关注的好友
        Set<Long> collect = lambdaQuery()
                .eq(Attention::getUserId, userId).list()
                .stream().map(Attention::getAimUserId).collect(Collectors.toSet());
        if (collect.isEmpty()) return PageUtils.pages(userPage, CollectionUtils.emptyList());
        //然后从这些中查询关注我的
        Page<Attention> page = lambdaQuery()
                .in(Attention::getUserId, collect)
                .eq(Attention::getAimUserId, userId).page(userPage);
        List<UserFansInfo> userSearchInfos = new ArrayList<>();
        for (Attention attention : page.getRecords()) {
            Attention one = lambdaQuery().eq(Attention::getUserId, userId).eq(Attention::getAimUserId, attention.getUserId()).one();
            User userInfo = iUserService.findUserInfo(attention.getUserId());
            UserFansInfo build = UserFansInfo.builder()
                    .id(attention.getId())
                    .userId(userInfo.getId())
                    .phone(userInfo.getPhone())
                    .photo(userInfo.getPhoto())
                    .nickname(userInfo.getNickName())
                    .isAttention(isAttention(userId, attention.getAimUserId()))
                    .createTime(attention.getCreateTime())
                    .noteName(!CommonUtils.isNull(one) ? one.getNoteName() : "")
                    .isBlock(attention.getIsBlock())
                    .isLook(attention.getIsLook())
                    .build();
            userSearchInfos.add(build);
        }
        return PageUtils.pages(page, userSearchInfos);
    }

    @Override
    public boolean setNote(AppUserSetNoteNameRequest request, Long userId) {
        Attention one = lambdaQuery().eq(Attention::getUserId, userId).eq(Attention::getAimUserId, request.getAimUserId()).one();
        Assert.notNull(one, "对方还未关注无法设置备注");
        one.setNoteName(request.getNoteName());
        return updateById(one);
    }

    @Override
    public Integer isLook(AppUserSetIsLookRequest request, Long userId) {
        Attention one = null;
        if (request.getType().equals(0)) {
            one = lambdaQuery().eq(Attention::getUserId, userId).eq(Attention::getAimUserId, request.getAimUserId()).one();
        } else {
            one = lambdaQuery().eq(Attention::getAimUserId, userId).eq(Attention::getUserId, request.getAimUserId()).one();
        }
        Assert.notNull(one, "无此好友");
        one.setIsLook(one.getIsLook().equals(0) ? 1 : 0);
        updateById(one);
        return one.getIsLook();
    }

    @Override
    public Integer isBlock(AppUserSetIsLookRequest request, Long userId) {
        Attention one;
        if (request.getType().equals(0)) {
            one = lambdaQuery().eq(Attention::getUserId, userId).eq(Attention::getAimUserId, request.getAimUserId()).one();
        } else {
            one = lambdaQuery().eq(Attention::getAimUserId, userId).eq(Attention::getUserId, request.getAimUserId()).one();
        }
        Assert.notNull(one, "无此好友");
        one.setIsBlock(one.getIsBlock().equals(0) ? 1 : 0);
        updateById(one);
        return one.getIsBlock();
    }

    @Override
    public Attention findById(Long userId, Long aimUserId) {
        return lambdaQuery().eq(Attention::getUserId, userId).eq(Attention::getAimUserId, aimUserId).one();
    }

    @Override
    public boolean undockFensi(Long aimUserId, Long userId) {
        Attention one = lambdaQuery().eq(Attention::getAimUserId, userId).eq(Attention::getUserId, aimUserId).one();
        Assert.notNull(one, "对方不是我粉丝 无法移除");
        return removeById(one.getId());
    }

    @Override
    public Integer isMyFens(Long userId, Long aimUserId) {
        Long count = lambdaQuery().eq(Attention::getUserId, aimUserId).eq(Attention::getAimUserId, userId).count();
        if (count > 0) return 1;
        return 0;
    }

    @Override
    public String aimNoteName(Long userId, Long aimUserId) {
        Attention one = lambdaQuery().eq(Attention::getAimUserId, userId).eq(Attention::getUserId, aimUserId).one();
        if (!CommonUtils.isNull(one)) return one.getNoteName();
        return "";
    }

    @Override
    public void read(Long userId) {
        lambdaUpdate().eq(Attention::getAimUserId, userId)
                .ne(Attention::getUserId, userId)
                .eq(Attention::getIsRead, UserConstant.Read.not)
                .set(Attention::getIsRead, UserConstant.Read.yes)
                .update();
    }
}
